﻿
Imports md5 = safty.md5Calculator
Imports sha1 = safty.sha1Calculator

Public Class multihashset(Of T As toBytes, SIZE As _int64)
    Private Shared _size As Int64 = 0
    Private normalhash As bitarray = Nothing
    Private md5hash As bitarray = Nothing
    Private sha1hash As bitarray = Nothing

    Shared Sub New()
        _size = +(alloc(Of SIZE)())
        Dim a As Object = Nothing
    End Sub

    Public Sub New()
        normalhash = New bitarray(_size)
        md5hash = New bitarray(_size)
        sha1hash = New bitarray(_size)
    End Sub

    Private Function uint64_hash(ByVal i As UInt64) As Int64
        Return i Mod _size
    End Function

    Private Function bytes_uint64(ByVal bs() As Byte) As UInt64
        assert(Not bs Is Nothing AndAlso bs.Length() > 0)
        Dim rtn As UInt64 = 0
        For i As Int64 = 0 To bs.Length() - 1
            rtn <<= bitcountInByte
            rtn += bs(i)
        Next
        Return rtn
    End Function

    Private Function bytes_hash(ByVal bs() As Byte) As Int64
        Return uint64_hash(bytes_uint64(bs))
    End Function

    Private Function _normal(ByVal i As T) As Int64
        assert(Not i Is Nothing)
        Return uint64_hash(i.GetHashCode())
    End Function

    Private Delegate Function hashDelegate(ByVal i() As Byte, ByRef rtn() As Byte) As Boolean

    Private Function hash(ByVal i As T, ByVal signing As hashDelegate) As Int64
        assert(Not i Is Nothing)
        assert(Not signing Is Nothing)
        Dim bts() As Byte = Nothing
        If signing(+(i.tobytes()), bts) Then
            Return bytes_hash(bts)
        Else
            Return 0
        End If
    End Function

    Private Function _md5(ByVal i As T) As Int64
        Return hash(i, AddressOf md5.signing)
    End Function

    Private Function _sha1(ByVal i As T) As Int64
        Return hash(i, AddressOf sha1.signing)
    End Function

    Public Function have(ByVal i As T) As Boolean
        If i Is Nothing Then
            Return False
        Else
            Return normalhash(_normal(i)) AndAlso md5hash(_md5(i)) AndAlso sha1hash(_sha1(i))
        End If
    End Function

    Public Function [set](ByVal i As T) As Boolean
        If i Is Nothing Then
            Return False
        Else
            normalhash(_normal(i)) = True
            md5hash(_md5(i)) = True
            sha1hash(_sha1(i)) = True
            If isdebugmode() Then
                assert(have(i))
            End If
            Return True
        End If
    End Function

    Default Property at(ByVal i As T) As Boolean
        Get
            Return have(i)
        End Get
        Set(ByVal __NOT_IN_USE__ As Boolean)
            [set](i)
        End Set
    End Property
End Class

Public Class multihashset(Of T As toBytes)
    Inherits multihashset(Of T, _131071)
End Class